//The MIT License
//
//Copyright (c) 2009 nodchip
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
package tv.dyndns.kishibe.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import tv.dyndns.kishibe.client.packet.PacketProblemData;

public class ProblemReportManager {
	private static final Comparator<PacketProblemData> COMPARATOR_PROBLEM_ID = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.problemId - o2.problemId;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_GENRE = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.genre - o2.genre;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_TYPE = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.type - o2.type;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_RANDOM_FLAG = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.randomFlag - o2.randomFlag;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_SENTENCE = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.sentence.compareTo(o2.sentence);
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_NOTE = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.note.compareTo(o2.note);
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_CREATOR = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.creator.compareTo(o2.creator);
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_CORRECT = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.good - o2.good;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_WRONG = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.bad - o2.bad;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_COUNT = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return (o1.good + o1.bad) - (o2.good + o2.bad);
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_RATIO = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.getCorrectRatio() - o2.getCorrectRatio();
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_VOTE_GOOD = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.voteGood - o2.voteGood;
		}
	};
	private static final Comparator<PacketProblemData> COMPARATOR_VOTE_BAD = new Comparator<PacketProblemData>() {
		public int compare(PacketProblemData o1, PacketProblemData o2) {
			return o1.voteBad - o2.voteBad;
		}
	};
	private static final List<Comparator<PacketProblemData>> COMPARATORS = createComparators();
	public static final int SORT_BY_PROBLEM_ID = 0;
	public static final int SORT_BY_GENRE = 1;
	public static final int SORT_BY_TYPE = 2;
	public static final int SORT_BY_FLAG = 3;
	public static final int SORT_BY_SENTENCE = 4;
	public static final int SORT_BY_NOTE = 5;
	public static final int SORT_BY_CREATOR = 6;
	public static final int SORT_BY_CORRECT = 7;
	public static final int SORT_BY_WRONG = 8;
	public static final int SORT_BY_COUNT = 9;
	public static final int SORT_BY_RATIO = 10;
	public static final int SORT_BY_VOTE_GOOD = 11;
	public static final int SORT_BY_VOTE_BAD = 12;
	private final PacketProblemData[] problems;
	private int lastSortBy = -1;

	private static List<Comparator<PacketProblemData>> createComparators() {
		final List<Comparator<PacketProblemData>> comparators = new ArrayList<Comparator<PacketProblemData>>();
		comparators.add(COMPARATOR_PROBLEM_ID);
		comparators.add(COMPARATOR_GENRE);
		comparators.add(COMPARATOR_TYPE);
		comparators.add(COMPARATOR_RANDOM_FLAG);
		comparators.add(COMPARATOR_SENTENCE);
		comparators.add(COMPARATOR_NOTE);
		comparators.add(COMPARATOR_CREATOR);
		comparators.add(COMPARATOR_CORRECT);
		comparators.add(COMPARATOR_WRONG);
		comparators.add(COMPARATOR_COUNT);
		comparators.add(COMPARATOR_RATIO);
		comparators.add(COMPARATOR_VOTE_GOOD);
		comparators.add(COMPARATOR_VOTE_BAD);
		return comparators;
	}

	public ProblemReportManager(PacketProblemData[] problems) {
		this.problems = problems;

		final int numberOfProblems = problems.length;
		for (int i = 0; i < numberOfProblems; ++i) {
			final PacketProblemData problemData = problems[i];
			problemData.sentence = problemData.getProblemReportSentence();
		}
	}

	public void sort(int sortBy) {
		if (sortBy < 0 || COMPARATORS.size() <= sortBy) {
			return;
		}

		// 前回と同じ選択の場合はリバース
		if (lastSortBy == sortBy) {
			reverse(getProblems());
			return;
		}

		lastSortBy = sortBy;
		Arrays.sort(getProblems(), COMPARATORS.get(sortBy));
	}

	private void reverse(Object[] o) {
		for (int left = 0, right = o.length - 1; left < right; ++left, --right) {
			final Object temp = o[left];
			o[left] = o[right];
			o[right] = temp;
		}
	}

	public PacketProblemData[] getProblems() {
		return problems;
	}
}
